home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / main / digi.c < prev    next >
C/C++ Source or Header  |  1998-04-03  |  41KB  |  1,464 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/main/digi.c,v $
  15.  * $Revision: 1.3 $
  16.  * $Author: hfrieden $
  17.  * $Date: 1998/04/03 13:32:52 $
  18.  * 
  19.  * Routines to access digital sound hardware
  20.  *
  21.  * $Log: digi.c,v $
  22.  * Revision 1.3  1998/04/03 13:32:52  hfrieden
  23.  * Added error messages
  24.  *
  25.  * Revision 1.2  1998/03/13 23:44:52  tfrieden
  26.  * *** empty log message ***
  27.  *
  28.  * Revision 1.1.1.1  1998/03/03 15:12:21  nobody
  29.  * reimport after crash from backup
  30.  *
  31.  * Revision 1.6  1998/02/21 23:15:54  hfrieden
  32.  * *** empty log message ***
  33.  *
  34.  * Revision 1.5  1998/02/18 17:15:23  hfrieden
  35.  * AHI Support finally working. Digital sound available
  36.  *
  37.  * Revision 1.4  1998/02/17 18:59:40  hfrieden
  38.  * Bugfixes on AHI driver
  39.  *
  40.  * Revision 1.3  1998/02/16 22:02:01  hfrieden
  41.  * Almost working AHI support
  42.  *
  43.  * Revision 1.2  1998/02/14 10:07:40  hfrieden
  44.  * AHI sound support added
  45.  *
  46.  */
  47.  
  48. #pragma off (unreferenced)
  49. static char rcsid[] = "$Id: digi.c,v 1.3 1998/04/03 13:32:52 hfrieden Exp $";
  50. #pragma on (unreferenced)
  51.  
  52. #include <stdlib.h>
  53. #include <stdio.h>
  54. #include <fcntl.h>
  55. #include <malloc.h>
  56. #include <string.h>
  57. #include <ctype.h>
  58.  
  59. #include "fix.h"
  60. #include "object.h"
  61. #include "mono.h"
  62. #include "timer.h"
  63. #include "joy.h"
  64. #include "digi.h"
  65. #include "sounds.h"
  66. #include "args.h"
  67. #include "key.h"
  68. #include "newdemo.h"
  69. #include "game.h"
  70. #include "error.h"
  71. #include "wall.h"
  72. #include "cfile.h"
  73. #include "piggy.h"
  74. #include "text.h"
  75. #include "gauges.h"
  76. #include "byteswap.h"
  77.  
  78. #include <exec/exec.h>
  79. #include <devices/ahi.h>
  80. #include <clib/alib_protos.h>
  81. #include <clib/exec_protos.h>
  82. #include <clib/utility_protos.h>
  83. #include <inline/exec.h>
  84. #include <inline/ahi.h>
  85. #include <inline/ahi_sub.h>
  86. #include <inline/utility.h>
  87.  
  88.  
  89. // #pragma pack (4);                        // Use 32-bit packing!
  90. #pragma off (check_stack);          // No stack checking!
  91. //*************************************************
  92. //#include "sos.h"
  93. //#include "sosm.h"
  94. //The above two includes are part of a commercial 
  95. //sound library, so they cannot be included in a public 
  96. //release of the source code. -KRB
  97. //#include "no_sos.h" //Added by KRB
  98. //*************************************************
  99. #include "kconfig.h"
  100. //#include "soscomp.h"
  101.  
  102. #define hp  HUD_init_message
  103.  
  104. #define DIGI_PAUSE_BROKEN 1     //if this is defined, don't pause MIDI songs
  105.  
  106. #define _DIGI_SAMPLE_FLAGS (_VOLUME | _PANNING )
  107.  
  108. #define _DIGI_MAX_VOLUME (16384)    //16384
  109.  
  110. // patch files
  111. #define  _MELODIC_PATCH       "melodic.bnk"
  112. #define  _DRUM_PATCH          "drum.bnk"
  113. #define  _DIGDRUM_PATCH       "drum32.dig"
  114.  
  115.  
  116. static int  Digi_initialized        = 0;
  117. static int  digi_atexit_called  = 0;            // Set to 1 if atexit(digi_close) was called
  118.  
  119. int ahidigi_audio_mode = AHI_DEFAULT_ID;
  120. int ahidigi_audio_freq = AHI_DEFAULT_FREQ;
  121. int ahidigi_next_channel = 0;
  122. int ahidigi_max_channels = 16;
  123. int ahidigi_volume_boost = 1;
  124. ULONG ahidigi_stereo = 0;
  125. ULONG ahidigi_panning = 0;
  126.  
  127. int digi_driver_board               = 100;      // Hey, this is an Amiga, man.
  128. int digi_driver_port                    = 100;
  129. int digi_driver_irq                 = 100;
  130. int digi_driver_dma                 = 100;
  131. int digi_midi_type                  = 0;            // Midi driver type
  132. int digi_midi_port                  = 0;            // Midi driver port
  133. static int digi_max_channels        = 16;
  134. static int digi_driver_rate     = 11025;            // rate to use driver at
  135. static int digi_dma_buffersize  = 4096;         // size of the dma buffer to use (4k)
  136. int digi_timer_rate                 = 9943;         // rate for the timer to go off to handle the driver system (120 Hz)
  137. int digi_lomem                      = 0;
  138. static int digi_volume              = _DIGI_MAX_VOLUME;     // Max volume
  139. static int midi_volume              = 128/2;                        // Max volume
  140. static int midi_system_initialized      = 0;
  141. static int digi_system_initialized      = 0;
  142. static int timer_system_initialized     = 0;
  143. static int digi_sound_locks[MAX_SOUNDS];
  144. char digi_last_midi_song[16] = "";
  145. char digi_last_melodic_bank[16] = "";
  146. char digi_last_drum_bank[16] = "";
  147. typedef char * LPSTR;
  148. //typedef ushort WORD;
  149. LPSTR digi_driver_path = NULL;//Was _NULL -KRB
  150. static WORD                     hSOSDigiDriver = 0xffff;            // handle for the SOS driver being used 
  151. static WORD                     hSOSMidiDriver = 0xffff;            // handle for the loaded MIDI driver
  152. static WORD                     hTimerEventHandle = 0xffff;     // handle for the timer function
  153.  
  154. void digi_reset_digi_sounds(void);
  155.  
  156. static void * lpInstruments = NULL;     // pointer to the instrument file
  157. static int InstrumentSize = 0;
  158. static void * lpDrums = NULL;               // pointer to the drum file
  159. static int DrumSize = 0;
  160. // track mapping structure, this is used to map which track goes
  161. // out which device. this can also be mapped by the name of the 
  162. // midi track. to map by the name of the midi track use the define
  163. // _MIDI_MAP_TRACK for each of the tracks 
  164. /*
  165. static _SOS_MIDI_TRACK_DEVICE   sSOSTrackMap = { 
  166.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, 
  167.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, 
  168.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, 
  169.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK,
  170.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, 
  171.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, 
  172.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, 
  173.    _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK, _MIDI_MAP_TRACK 
  174. };
  175. */
  176. // handle for the initialized MIDI song
  177. WORD     wSongHandle = 0xffff;         
  178. ubyte       *SongData=NULL;
  179. int     SongSize;
  180.  
  181.  
  182. #define SOF_USED                1       // Set if this sample is used
  183. #define SOF_PLAYING         2       // Set if this sample is playing on a channel
  184. #define SOF_LINK_TO_OBJ     4       // Sound is linked to a moving object. If object dies, then finishes play and quits.
  185. #define SOF_LINK_TO_POS     8       // Sound is linked to segment, pos
  186. #define SOF_PLAY_FOREVER    16      // Play forever (or until level is stopped), otherwise plays once
  187.  
  188. typedef struct sound_object {
  189.     short           signature;      // A unique signature to this sound
  190.     ubyte           flags;          // Used to tell if this slot is used and/or currently playing, and how long.
  191.     fix         max_volume;     // Max volume that this sound is playing at
  192.     fix         max_distance;   // The max distance that this sound can be heard at...
  193.     int         volume;         // Volume that this sound is playing at
  194.     int         pan;                // Pan value that this sound is playing at
  195.     WORD            handle;         // What handle this sound is playing on.  Valid only if SOF_PLAYING is set.
  196.     short           soundnum;       // The sound number that is playing
  197.     int             channel;        // AHI channel number this sound is playing on
  198.     union { 
  199.         struct {
  200.             short           segnum;             // Used if SOF_LINK_TO_POS field is used
  201.             short           sidenum;                
  202.             vms_vector  position;
  203.         } s1;
  204.         struct {
  205.             short           objnum;             // Used if SOF_LINK_TO_OBJ field is used
  206.             short           objsignature;
  207.         } s2;
  208.     } u;
  209. } sound_object;
  210.  
  211. #define _segnum         u.s1.segnum
  212. #define _sidenum        u.s1.sidenum
  213. #define _position       u.s1.position
  214. #define _objnum         u.s2.objnum
  215. #define _objsignature   u.s2.objsignature
  216.  
  217. #define MAX_SOUND_OBJECTS 16
  218. sound_object SoundObjects[MAX_SOUND_OBJECTS];
  219. short next_signature=0;
  220.  
  221. struct MsgPort *AudioPort = NULL;
  222. char AHIDevice = -1;
  223. struct AHIRequest *MasterRequest;
  224. struct Library *AHIBase;
  225. struct AHIAudioCtrl *AudioCtrl;
  226.  
  227. int ChannelMap[32];
  228.  
  229. struct AHIEffMasterVolume ahidigi_master_volume;
  230.  
  231. struct Hook ahidigi_hook;
  232.  
  233. typedef struct ahidigi_param {
  234.     int         nLoop;
  235.     Fixed       Volume;
  236.     int         Size;
  237.     UBYTE *     Data;
  238.     sposition   Pan;
  239. } ahidigi_param;
  240.  
  241. extern struct Library *SysBase;
  242.  
  243. #define AHIDIGI_PAN_CENTER  0x8000L
  244. #define AHIDIGI_VOL_MAX     0x10000L
  245.  
  246. int digi_sounds_initialized=0;
  247. //this block commented out by KRB
  248.  
  249.  
  250. void * testLoadFile( char * szFileName, int * length );
  251.  
  252. void sosMIDICallback( WORD PassedSongHandle );
  253. void sosEndMIDICallback();
  254.  
  255. int digi_xlat_sound(int soundno)
  256. {
  257.  
  258.     if ( soundno < 0 ) return -1;
  259.  
  260.     if ( digi_lomem )   {
  261.         soundno = AltSounds[soundno];
  262.         if ( soundno == 255 ) return -1;
  263.     }
  264.     return Sounds[soundno];
  265.  
  266. }
  267.  
  268.  
  269. void digi_close_midi()
  270. {
  271. /*
  272.     if (digi_midi_type>0)   {
  273.         if (wSongHandle < 0xffff)   {
  274.            // stop the last MIDI song from playing
  275.             sosMIDIStopSong( wSongHandle );
  276.            // uninitialize the last MIDI song
  277.             sosMIDIUnInitSong( wSongHandle );
  278.             wSongHandle = 0xffff;
  279.         }
  280.         if (SongData)   {
  281.             if (!dpmi_unlock_region(SongData, SongSize))    {
  282.                 mprintf( (1, "Error unlocking midi file" ));
  283.             }
  284.             free(SongData);
  285.             SongData = NULL;
  286.         }
  287.        // reset the midi driver and
  288.        // uninitialize the midi driver and tell it to free the memory allocated
  289.        // for the driver
  290.         if ( hSOSMidiDriver < 0xffff )  {
  291.            sosMIDIResetDriver( hSOSMidiDriver );
  292.         sosMIDIUnInitDriver( hSOSMidiDriver, _TRUE  );
  293.             hSOSMidiDriver = 0xffff;
  294.         }
  295.  
  296.         if ( midi_system_initialized )  {
  297.            // uninitialize the MIDI system
  298.            sosMIDIUnInitSystem(); 
  299.             midi_system_initialized = 0;
  300.         }
  301.     }
  302. */
  303. }
  304.  
  305. void digi_close_digi()
  306. {
  307.     if (AHIBase && AudioCtrl) {
  308.         ahidigi_master_volume.ahie_Effect = AHIET_CANCEL|AHIET_MASTERVOLUME;
  309.         AHI_SetEffect(&ahidigi_master_volume, AudioCtrl);
  310.     }
  311.     if (!AHIDevice) {
  312.         //AbortIO((struct IORequest *)MasterRequest);
  313.         CloseDevice((struct IORequest *)MasterRequest);
  314.         AHIDevice = -1;
  315.     }
  316.     if (AudioCtrl)     AHI_FreeAudio(AudioCtrl);
  317.     if (MasterRequest) DeleteIORequest((struct IORequest *)MasterRequest);
  318.     if (AudioPort)     DeleteMsgPort(AudioPort);
  319. }
  320.  
  321.  
  322. void digi_close()
  323. {
  324.     if (!Digi_initialized) return;
  325.     Digi_initialized = 0;
  326.  
  327.     digi_close_midi();
  328.     digi_close_digi();
  329.  
  330.     if ( digi_system_initialized )  {
  331.         digi_system_initialized = 0;
  332.     }
  333. }
  334.  
  335. extern int loadpats( char * filename );
  336.  
  337. int digi_load_fm_banks( char * melodic_file, char * drum_file )
  338. {   
  339. /*
  340.    WORD     wError;                 // error code returned from functions
  341.  
  342.     // set the instrument file for the MIDI driver to use, since we are using
  343.     // the FM driver two instrument files are needed, the first is for 
  344.     // all melodic instruments and the second is for events on channel 10
  345.     // which is the drum track.
  346.     // set the drum instruments
  347.     if (lpInstruments)  {
  348.         dpmi_unlock_region(lpInstruments, InstrumentSize);
  349.         free( lpInstruments );
  350.     }
  351.             
  352.     lpInstruments = testLoadFile( melodic_file, &InstrumentSize );
  353.     if ( !lpInstruments )   {
  354.         printf( "%s '%s'\n", TXT_SOUND_ERROR_OPEN, melodic_file );
  355.         return 0;
  356.     }
  357.  
  358.     if (!dpmi_lock_region(lpInstruments, InstrumentSize))   {
  359.         printf( "%s '%s', ptr=0x%8x, len=%d bytes\n", TXT_SOUND_ERROR_LOCK, melodic_file, lpInstruments, InstrumentSize );
  360.         return 0;
  361.     }
  362.     
  363.     if( ( wError =  sosMIDISetInsData( hSOSMidiDriver, lpInstruments, 0x01  ) ) )   {
  364.         printf( "%s %s \n", TXT_SOUND_ERROR_HMI, sosGetErrorString( wError ) );
  365.         return 0;
  366.     }
  367.     
  368.     if (lpDrums)    {
  369.         dpmi_unlock_region(lpDrums, DrumSize);
  370.         free( lpDrums );
  371.     }
  372.             
  373.     lpDrums = testLoadFile( drum_file, &DrumSize );
  374.     if ( !lpDrums ) {
  375.         printf( "%s '%s'\n", TXT_SOUND_ERROR_OPEN, drum_file );
  376.         return 0;
  377.     }
  378.  
  379.     if (!dpmi_lock_region(lpDrums, DrumSize))   {
  380.         printf( "%s  '%s', ptr=0x%8x, len=%d bytes\n", TXT_SOUND_ERROR_LOCK_DRUMS, drum_file, lpDrums, DrumSize );
  381.         return 0;
  382.     }
  383.     
  384.      // set the drum instruments
  385.     if( ( wError =  sosMIDISetInsData( hSOSMidiDriver, lpDrums, 0x01  ) ) ) {
  386.         printf( "%s %s\n", TXT_SOUND_ERROR_HMI, sosGetErrorString( wError ) );
  387.         return 0;
  388.     }
  389.     
  390.     return 1;
  391. */
  392.     return 0;//KRB Comment out...
  393.  
  394. }
  395.  
  396. int digi_init_midi()
  397. {
  398. /*
  399.    WORD     wError;                 // error code returned from functions
  400.     _SOS_MIDI_INIT_DRIVER           sSOSMIDIInitDriver; // structure for the MIDI driver initialization function 
  401.     _SOS_MIDI_HARDWARE              sSOSMIDIHardware;   // structure for the MIDI driver hardware
  402.  
  403.     if ( digi_midi_type > 0 )   {
  404.         // Lock the TrackMap array, since HMI references it in an interrupt.
  405.         if (!dpmi_lock_region ( &sSOSTrackMap, sizeof(sSOSTrackMap)) )  {
  406.             printf( "%s\n", TXT_SOUND_ERROR_MIDI);
  407.             digi_close();
  408.             return 1;
  409.         }
  410.  
  411. //      if (!dpmi_lock_region ((void near *)sosMIDICallback, (char *)sosEndMIDICallback - (char near *)sosMIDICallback))    {
  412.         if (!dpmi_lock_region ((void near *)sosMIDICallback, 4*1024) )  {
  413.             printf( "%s\n", TXT_SOUND_ERROR_MIDI_CALLBACK);
  414.             digi_close();
  415.             return 1;
  416.         }
  417.  
  418.        // initialize the MIDI system
  419.        sosMIDIInitSystem( digi_driver_path, _SOS_DEBUG_NORMAL );
  420.         midi_system_initialized = 1;
  421.  
  422.        // set the pointer to the driver memory for the MIDI driver to 
  423.        // _NULL. this will tell the load driver routine to allocate new
  424.        // memory for the MIDI driver
  425.        sSOSMIDIInitDriver.lpDriverMemory  = _NULL;
  426.         sSOSMIDIInitDriver.sDIGIInitInfo = _NULL;
  427.     
  428.         sSOSMIDIHardware.wPort = digi_midi_port;
  429.     
  430.        // load and initialize the MIDI driver 
  431.        if( ( wError = sosMIDIInitDriver( digi_midi_type, &sSOSMIDIHardware, &sSOSMIDIInitDriver, &hSOSMidiDriver ) ) )  {
  432.           printf( "SOUND: (HMI) '%s'\n", sosGetErrorString( wError ) );
  433.             digi_close();
  434.           return 1;
  435.        }
  436.         sosMIDIEnableChannelStealing( _FALSE );
  437.     }
  438.     return 0;
  439. */
  440.     return 0;//KRB Comment out...
  441.  
  442. }
  443.  
  444. void __interrupt __saveds ahidigi_callback(struct Hook *hook __asm("a0"), struct AHIAudioCtrl *actrl __asm("a2"), struct AHISoundMessage *msg __asm("a1"))
  445. {
  446.     ChannelMap[msg->ahism_Channel] = 1-ChannelMap[msg->ahism_Channel];
  447. }
  448.  
  449. int digi_init_digi()
  450. {
  451.     int i;
  452.     ULONG error;
  453.  
  454.     AudioPort = CreateMsgPort();
  455.     if (!AudioPort) return 1;
  456. #ifdef DEBUG_SOUND
  457.     printf("digi_init_digi: Message Port created\n");
  458. #endif
  459.  
  460.     MasterRequest = (struct AHIRequest *)CreateIORequest(AudioPort, sizeof(struct AHIRequest));
  461.     if (MasterRequest) {
  462. #ifdef DEBUG_SOUND
  463.     printf("digi_init_digi: IORequest created\n");
  464. #endif
  465.         MasterRequest -> ahir_Version = 4;
  466.         AHIDevice = (char)OpenDevice((unsigned char *)AHINAME,
  467.             (unsigned long)AHI_NO_UNIT, (struct IORequest *)MasterRequest, 0);
  468.     }
  469.  
  470.     if (AHIDevice) {
  471. #ifdef DEBUG_SOUND
  472.     printf("digi_init_digi: AHIDevice open error %d\n", AHIDevice);
  473. #endif
  474.         if (MasterRequest) DeleteIORequest((struct IORequest *)MasterRequest);
  475.         if (AudioPort) DeleteMsgPort(AudioPort);
  476.         printf("FATAL ERROR: Cannot initalized AHI device\n");
  477.         return 1;
  478.     }
  479.  
  480.     AHIBase = (struct Library *)MasterRequest->ahir_Std.io_Device;
  481. #ifdef DEBUG_SOUND
  482.     printf("digi_init_digi: AHIDevice created, allocating audio\n");
  483. #endif
  484.  
  485.     ahidigi_hook.h_Entry = (HOOKFUNC)ahidigi_callback;
  486.     ahidigi_hook.h_SubEntry = 0;
  487.  
  488.     AudioCtrl = AHI_AllocAudio(
  489.         AHIA_AudioID,       ahidigi_audio_mode,
  490.         AHIA_MixFreq,       ahidigi_audio_freq,
  491.         AHIA_Channels,      (ULONG)ahidigi_max_channels,
  492.         AHIA_Sounds,        30,
  493.         //AHIA_SoundFunc,     (ULONG)&ahidigi_hook,
  494.     TAG_DONE);
  495.  
  496. #ifdef DEBUG_SOUND
  497.     printf("digi_init_digi: AudioCtrl = %d\n", AudioCtrl);
  498. #endif
  499.  
  500.     if (AudioCtrl == NULL) {
  501.         printf("FATAL ERROR: Cannot initialize AudioCtrl\n");
  502.         return 1;
  503.     }
  504. #ifdef DEBUG_SOUND
  505.     printf("digi_init_digi: AudioCtrl allocated and done\n");
  506. #endif
  507.  
  508.     AHI_GetAudioAttrs(ahidigi_audio_mode, NULL,
  509.         AHIDB_Stereo,   (ULONG)&ahidigi_stereo,
  510.         AHIDB_Panning,  (ULONG)&ahidigi_panning,
  511.     TAG_DONE);
  512.  
  513.  
  514.     for (i=0; i<32; i++) ChannelMap[i] = 0;
  515.  
  516.     ahidigi_master_volume.ahie_Effect = AHIET_MASTERVOLUME;
  517.     //i = (ahidigi_stereo && !ahidigi_panning) ? 4 : 2;
  518.     ahidigi_master_volume.ahiemv_Volume = ahidigi_volume_boost * 65535;
  519.     error = AHI_SetEffect(&ahidigi_master_volume, AudioCtrl);
  520.  
  521.     digi_set_digi_volume ( (Config_digi_volume * 32768)/8);
  522.  
  523. #ifdef DEBUG_SOUND
  524.     printf("Done\n");
  525. #endif
  526.  
  527.     return 0;
  528. }
  529.  
  530. int digi_init()
  531. {
  532.     int i;
  533.     if ( FindArg( "-nomusic" )) 
  534.         digi_midi_type = 0;
  535.  
  536.  
  537.     Digi_initialized = 1;
  538.     digi_system_initialized = 1;
  539.  
  540.     if (digi_init_midi()) return 1;
  541.     if (digi_init_digi()) return 1;
  542.  
  543.     if (!digi_atexit_called)    {
  544.         atexit( digi_close );
  545.         digi_atexit_called = 1;
  546.     }
  547.  
  548.     digi_init_sounds();
  549.     digi_set_midi_volume( midi_volume );
  550.  
  551.     for (i=0; i<MAX_SOUNDS; i++ )
  552.         digi_sound_locks[i] = 0;
  553.     digi_reset_digi_sounds();
  554.  
  555.     return 0;
  556. }
  557.  
  558. // Toggles sound system on/off
  559. void digi_reset()   
  560. {
  561.     if ( Digi_initialized ) {
  562.         digi_reset_digi_sounds();
  563.         digi_close();
  564.         mprintf( (0, "Sound system DISABLED.\n" ));
  565.     } else {
  566.         digi_init();
  567.         mprintf( (0, "Sound system ENABLED.\n" ));
  568.     }
  569. }
  570.  
  571. int digi_total_locks = 0;
  572.  
  573. ubyte * digi_lock_sound_data( int soundnum )
  574. {
  575. /*
  576.     int i;
  577.  
  578.     if ( !Digi_initialized ) return NULL;
  579.     if ( digi_driver_board <= 0 )   return NULL;
  580.  
  581.     if ( digi_sound_locks[soundnum] == 0 )  {
  582.         digi_total_locks++;
  583.         //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
  584.         i = dpmi_lock_region( GameSounds[soundnum].data, GameSounds[soundnum].length );
  585.         if ( !i ) Error( "Error locking sound %d\n", soundnum );
  586.     }
  587.     digi_sound_locks[soundnum]++;
  588.     return GameSounds[soundnum].data;
  589. */
  590.     digi_total_locks=digi_total_locks;//blah -KRB
  591.     return 0;//KRB Comment out...
  592.  
  593. }
  594.  
  595. void digi_unlock_sound_data( int soundnum )
  596. {
  597. /*
  598.     int i;
  599.  
  600.     if ( !Digi_initialized ) return;
  601.     if ( digi_driver_board <= 0 )   return;
  602.  
  603.     Assert( digi_sound_locks[soundnum] > 0 );
  604.  
  605.     if ( digi_sound_locks[soundnum] == 1 )  {
  606.         digi_total_locks--;
  607.         //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
  608.         i = dpmi_unlock_region( GameSounds[soundnum].data, GameSounds[soundnum].length );
  609.         if ( !i ) Error( "Error unlocking sound %d\n", soundnum );
  610.     }
  611.     digi_sound_locks[soundnum]--;
  612. */
  613. }
  614. /*
  615. static int next_handle = 0;
  616. static WORD SampleHandles[32] = { 0xffff, 0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff };
  617. static int SoundNums[32] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };
  618. static uint SoundVolumes[32] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };
  619. //This block commented out by KRB
  620. */
  621. void digi_reset_digi_sounds(void)
  622. {
  623.     int i;
  624.  
  625.     if ( !Digi_initialized ) return;
  626.  
  627.     for (i=0; i<ahidigi_max_channels; i++)
  628.         AHI_SetSound((UWORD)i, AHI_NOSOUND, 0, 0, AudioCtrl, AHISF_IMM);
  629.  
  630.     for (i=0; i<32; i++) ChannelMap[i] = 0;
  631.     AHI_ControlAudio(AudioCtrl,
  632.         AHIC_Play, TRUE,
  633.     TAG_DONE);
  634.  
  635. }
  636.  
  637. void reset_sounds_on_channel( int channel )
  638. {
  639.     if ( !Digi_initialized ) return;
  640.     AHI_SetSound((UWORD)channel, AHI_NOSOUND, 0, 0, AudioCtrl, AHISF_IMM);
  641.     ChannelMap[channel] = 0;
  642.  
  643. }
  644.  
  645.  
  646. void digi_set_max_channels(int n)
  647. {
  648.     return;
  649. /*    digi_max_channels   = n;
  650.  
  651.     if ( digi_max_channels < 1 ) 
  652.         digi_max_channels = 1;
  653.     if ( digi_max_channels > (32-MAX_SOUND_OBJECTS) ) 
  654.         digi_max_channels = (32-MAX_SOUND_OBJECTS);
  655.  
  656.     if ( !Digi_initialized ) return;
  657.  
  658.     digi_reset_digi_sounds();*/
  659. }
  660.  
  661. int digi_get_max_channels()
  662. {
  663.     return ahidigi_max_channels;
  664.  
  665. }
  666.  
  667.  
  668. WORD digi_start_sound(ahidigi_param *sampledata, short soundnum )
  669.  
  670. {
  671.     int i,j;
  672.  
  673.     struct AHISampleInfo info;
  674.  
  675.     unsigned long volume;
  676.  
  677.     if ( !Digi_initialized ) return -1;
  678.  
  679.     // Start by finding a free channel
  680.  
  681.     i = ahidigi_next_channel;
  682.     j=0;
  683.     do {
  684.         ahidigi_next_channel++; j++;
  685.         if (ahidigi_next_channel == ahidigi_max_channels)
  686.             ahidigi_next_channel = 0;
  687.         if (ChannelMap[ahidigi_next_channel] == 0) break;
  688.     } while (j<32);
  689.  
  690.     info.ahisi_Type = AHIST_M8U;
  691.     info.ahisi_Address = sampledata->Data;
  692.     info.ahisi_Length = sampledata->Size;
  693.     AHI_LoadSound(i, AHIST_SAMPLE, &info, AudioCtrl);
  694.  
  695.     volume = (unsigned long)digi_volume*(unsigned long)(sampledata->Volume) / 65535UL;
  696.  
  697.     #ifdef DEBUG_SOUND
  698.     hp("Volume: %d (%d)",volume, i);
  699.     #endif
  700.  
  701.     if (sampledata->nLoop != 0) {
  702.         AHI_Play(AudioCtrl,
  703.             AHIP_BeginChannel,  i,
  704.             AHIP_Freq,      (ULONG)digi_driver_rate,
  705.             AHIP_Vol,       (ULONG)volume,
  706.             AHIP_Sound,     i,
  707.             AHIP_Pan,       sampledata->Pan,
  708.             AHIP_LoopFreq,  (ULONG)digi_driver_rate,
  709.             AHIP_LoopVol,   sampledata->Volume,
  710.             AHIP_LoopPan,   sampledata->Pan,
  711.             AHIP_EndChannel,NULL,
  712.         TAG_DONE);
  713.     } else {
  714.         AHI_Play(AudioCtrl,
  715.             AHIP_BeginChannel,  i,
  716.             AHIP_Freq,      (ULONG)digi_driver_rate,
  717.             AHIP_Vol,       (ULONG)volume,
  718.             AHIP_Pan,       sampledata->Pan,
  719.             AHIP_Sound,     i,
  720.             AHIP_LoopSound, AHI_NOSOUND,
  721.             AHIP_EndChannel,NULL,
  722.         TAG_DONE);
  723.         //AHI_SetSound(i, AHI_NOSOUND, 0,0, AudioCtrl, 0);
  724.     }
  725.  
  726.     #ifdef DEBUG_SOUND
  727.     {
  728.         int j;
  729.         char xxx[40];
  730.         for (j=0; j<ahidigi_max_channels; j++) xxx[j]='0'+ChannelMap[j];
  731.         xxx[j]=0;
  732.         hp("channels: %s", xxx);
  733.     }
  734.     #endif
  735.  
  736.     return i;
  737.  
  738. }
  739.  
  740. int digi_is_sound_playing(int soundno)
  741. {
  742.     return 0;//KRB Comment out...
  743. }
  744.  
  745. void digi_play_sample_once( int soundno, fix max_volume )   
  746. {
  747.     digi_sound *snd;
  748.     ahidigi_param params;
  749.  
  750. #ifdef NEWDEMO
  751.     if ( Newdemo_state == ND_STATE_RECORDING )
  752.         newdemo_record_sound( soundno );
  753. #endif
  754.     soundno = digi_xlat_sound(soundno);
  755.  
  756.     if (!Digi_initialized) return;
  757.  
  758.     if (soundno < 0 ) return;
  759.     snd = &GameSounds[soundno];
  760.  
  761.     params.nLoop        = 0;
  762.     params.Volume       = max_volume;
  763.     params.Size         = snd->length;
  764.     params.Data         = snd->data;
  765.     params.Pan          = AHIDIGI_PAN_CENTER;
  766.  
  767.     digi_start_sound( ¶ms, soundno );
  768. }
  769.  
  770.  
  771. void digi_play_sample( int soundno, fix max_volume )
  772. {
  773.     digi_play_sample_once(soundno, max_volume);
  774. }
  775.  
  776.  
  777. void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) 
  778. {
  779.     digi_sound *snd;
  780.     ahidigi_param params;
  781.  
  782. #ifdef NEWDEMO
  783.     if ( Newdemo_state == ND_STATE_RECORDING )
  784.         newdemo_record_sound( soundno );
  785. #endif
  786.     soundno = digi_xlat_sound(soundno);
  787.  
  788.     if (!Digi_initialized) return;
  789.  
  790.     if (soundno < 0 ) return;
  791.     snd = &GameSounds[soundno];
  792.  
  793.     params.nLoop        = 0;
  794.     params.Volume       = volume;
  795.     params.Size         = snd->length;
  796.     params.Data         = snd->data;
  797.     params.Pan          = angle;
  798.  
  799.  
  800.     digi_start_sound( ¶ms, soundno );
  801.  
  802. /*
  803.     sSOSSampleData.wSamplePanLocation   = angle;            // 0 - 0xFFFF
  804.     sSOSSampleData.wSamplePanSpeed      = 0;
  805.     sSOSSampleData.wVolume                  = fixmuldiv(volume,digi_volume,F1_0);;                  // 0 - 0x7fff
  806. */
  807. }
  808.  
  809. void digi_set_midi_volume( int mvolume )
  810. {
  811. /*
  812.     int old_volume = midi_volume;
  813.  
  814.     if ( mvolume > 127 )
  815.         midi_volume = 127;
  816.     else if ( mvolume < 0 )
  817.         midi_volume = 0;
  818.     else
  819.         midi_volume = mvolume;
  820.  
  821.     if ( (digi_midi_type > 0) && (hSOSMidiDriver < 0xffff) )        {
  822.         if (  (old_volume < 1) && ( midi_volume > 1 ) ) {
  823.             if (wSongHandle == 0xffff )
  824.                 digi_play_midi_song( digi_last_midi_song, digi_last_melodic_bank, digi_last_drum_bank, 1 );
  825.         }
  826.         _disable();
  827.         sosMIDISetMasterVolume(midi_volume);
  828.         _enable();
  829.     }
  830. */
  831. }
  832.  
  833. void digi_set_digi_volume( int dvolume )
  834. {
  835.     if ( !Digi_initialized ) return;
  836.  
  837.     if (dvolume <= 0)
  838.         digi_volume = 0;
  839.     else
  840.         digi_volume = dvolume*2-1;
  841.  
  842.     digi_sync_sounds();
  843.  
  844. }
  845.  
  846.  
  847. // 0-0x7FFF 
  848. void digi_set_volume( int dvolume, int mvolume )    
  849. {
  850.  
  851. #ifdef DEBUG_SOUND
  852.     printf("digi_set__volume(%d, %d)\n", dvolume, mvolume);
  853. #endif
  854.  
  855.     digi_set_midi_volume( mvolume );
  856.     digi_set_digi_volume( dvolume );
  857. }
  858.  
  859. // allocate memory for file, load file, create far pointer
  860. // with DS in selector.
  861. void * testLoadFile( char * szFileName, int * length )
  862. {
  863. /*
  864.    PSTR  pDataPtr;
  865.     CFILE * fp;
  866.     
  867.    // open file
  868.    fp  =  cfopen( szFileName, "rb" );
  869.     if ( !fp ) return NULL;
  870.  
  871.    *length  =  cfilelength(fp);
  872.  
  873.    pDataPtr =  malloc( *length );
  874.     if ( !pDataPtr ) return NULL;
  875.  
  876.    // read in driver
  877.    cfread( pDataPtr, *length, 1, fp);
  878.  
  879.    // close driver file
  880.    cfclose( fp );
  881.  
  882.    // return 
  883.    return( pDataPtr );
  884.    */
  885.    return NULL;//KRB Comment out...
  886. }
  887.  
  888.  
  889. // ALL VARIABLES IN HERE MUST BE LOCKED DOWN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  890. void sosMIDICallback( WORD PassedSongHandle )
  891. {
  892.     //sosMIDIStartSong(PassedSongHandle);
  893.     return;//KRB comment out
  894.  
  895. void sosEndMIDICallback()       // Used to mark the end of sosMIDICallBack
  896. {
  897. }
  898.  
  899. void digi_stop_current_song()
  900. {
  901. /*
  902.     // Stop last song...
  903.     if (wSongHandle < 0xffff )  {
  904.        // stop the last MIDI song from playing
  905.         sosMIDIStopSong( wSongHandle );
  906.        // uninitialize the last MIDI song
  907.         sosMIDIUnInitSong( wSongHandle );
  908.         wSongHandle = 0xffff;
  909.     }
  910.     if (SongData)   {
  911.         if (!dpmi_unlock_region(SongData, SongSize))    {
  912.             mprintf( (1, "Error unlocking midi file" ));
  913.         }
  914.         free(SongData);
  915.         SongData = NULL;
  916.     }
  917. */
  918. }
  919.  
  920.  
  921. void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
  922. {
  923. /*
  924.     int i;
  925.     char fname[128];
  926.    WORD     wError;                 // error code returned from functions
  927.     CFILE       *fp;
  928.  
  929.     // structure to pass sosMIDIInitSong
  930.     _SOS_MIDI_INIT_SONG     sSOSInitSong;
  931.  
  932.     if (!Digi_initialized) return;
  933.     if ( digi_midi_type <= 0 )  return;
  934.  
  935.     digi_stop_current_song();
  936.  
  937.     if ( filename == NULL ) return;
  938.  
  939.     strcpy( digi_last_midi_song, filename );
  940.     strcpy( digi_last_melodic_bank, melodic_bank );
  941.     strcpy( digi_last_drum_bank, drum_bank );
  942.  
  943.     fp = NULL;
  944.  
  945.     if ( (digi_midi_type==_MIDI_FM)||(digi_midi_type==_MIDI_OPL3) ) {   
  946.         int sl;
  947.         sl = strlen( filename );
  948.         strcpy( fname, filename );  
  949.         fname[sl-1] = 'q';
  950.         fp = cfopen( fname, "rb" );
  951.     }
  952.  
  953.     if ( !fp  ) {
  954.         fp = cfopen( filename, "rb" );
  955.         if (!fp) {
  956.             mprintf( (1, "Error opening midi file, '%s'", filename ));
  957.             return;
  958.         }
  959.     }
  960.     if ( midi_volume < 1 )      {
  961.         cfclose(fp);
  962.         return;             // Don't play song if volume == 0;
  963.     }
  964.     SongSize = cfilelength( fp );
  965.     SongData    = malloc( SongSize );
  966.     if (SongData==NULL) {
  967.         cfclose(fp);
  968.         mprintf( (1, "Error mallocing %d bytes for '%s'", SongSize, filename ));
  969.         return;
  970.     }
  971.     if ( cfread (  SongData, SongSize, 1, fp )!=1)  {
  972.         mprintf( (1, "Error reading midi file, '%s'", filename ));
  973.         cfclose(fp);
  974.         free(SongData);
  975.         SongData=NULL;
  976.         return;
  977.     }
  978.     cfclose(fp);
  979.  
  980.     if ( (digi_midi_type==_MIDI_FM)||(digi_midi_type==_MIDI_OPL3) ) {   
  981.         if ( !digi_load_fm_banks(melodic_bank, drum_bank) ) {
  982.             return;
  983.         }
  984.     }
  985.         
  986.     if (!dpmi_lock_region(SongData, SongSize))  {
  987.         mprintf( (1, "Error locking midi file, '%s'", filename ));
  988.         free(SongData);
  989.         SongData=NULL;
  990.         return;
  991.     }
  992.  
  993.     // setup the song initialization structure
  994.     sSOSInitSong.lpSongData = SongData;
  995.     if ( loop )
  996.         sSOSInitSong.lpSongCallback = sosMIDICallback;
  997.     else
  998.         sSOSInitSong.lpSongCallback = _NULL;
  999.  
  1000.     for ( i=0; i<32; i++ )
  1001.         sSOSTrackMap.wTrackDevice[i] = _MIDI_MAP_TRACK;
  1002.             
  1003.     for ( i=0; i<_SOS_MIDI_MAX_TRACKS; i++ )
  1004.         _lpSOSMIDITrack[0][i] = _NULL;
  1005.  
  1006.     //initialize the song
  1007.     if( ( wError = sosMIDIInitSong( &sSOSInitSong, &sSOSTrackMap, &wSongHandle ) ) )    {
  1008.         mprintf( (1, "\nHMI Error : %s", sosGetErrorString( wError ) ));
  1009.         free(SongData);
  1010.         SongData=NULL;
  1011.         return;
  1012.     }
  1013.  
  1014.     Assert( wSongHandle == 0 );
  1015.      
  1016.   // start the song playing
  1017.    if( ( wError = sosMIDIStartSong( wSongHandle ) ) ) {
  1018.         mprintf( (1, "\nHMI Error : %s", sosGetErrorString( wError ) ));
  1019.        // uninitialize the last MIDI song
  1020.         sosMIDIUnInitSong( wSongHandle );
  1021.         free(SongData);
  1022.         SongData=NULL;
  1023.         return;
  1024.    }
  1025.    */
  1026. }
  1027.  
  1028. void digi_get_sound_loc( vms_matrix * listener, vms_vector * listener_pos, int listener_seg, vms_vector * sound_pos, int sound_seg, fix max_volume, int *volume, int *pan, fix max_distance )   
  1029. {     
  1030.     vms_vector  vector_to_sound;
  1031.     fix angle_from_ear, cosang,sinang;
  1032.     fix distance;
  1033.     fix path_distance;
  1034.  
  1035.     *volume = 0;
  1036.     *pan = 0;
  1037.  
  1038.     max_distance = (max_distance*5)/4;      // Make all sounds travel 1.25 times as far.
  1039.  
  1040.     //  Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
  1041.     distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
  1042.         
  1043.     if (distance < max_distance )   {
  1044.         int num_search_segs = f2i(max_distance/20);
  1045.         if ( num_search_segs < 1 ) num_search_segs = 1;
  1046.  
  1047.         path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
  1048.         if ( path_distance > -1 )   {
  1049.             *volume = max_volume - fixdiv(path_distance,max_distance);
  1050.             //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
  1051.             if (*volume > 0 )   {
  1052.                 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
  1053.                 fix_sincos(angle_from_ear,&sinang,&cosang);
  1054.                 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
  1055.                 if (Config_channels_reversed) cosang *= -1;
  1056.                 *pan = (cosang + F1_0)/2;
  1057.             } else {
  1058.                 *volume = 0;
  1059.             }
  1060.         }
  1061.     }                                                                                     
  1062. }
  1063.  
  1064.  
  1065. void digi_init_sounds()
  1066. {
  1067.     int i;
  1068.  
  1069.     if (!Digi_initialized) return;
  1070.  
  1071.     digi_reset_digi_sounds();
  1072.  
  1073.     for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
  1074.         if (digi_sounds_initialized) {
  1075.             if ( SoundObjects[i].flags & SOF_PLAYING )  {
  1076.             }
  1077.         }
  1078.         #ifdef DEBUG_SOUND
  1079.         hp("SOF_PLAYING reset on %d");
  1080.         #endif
  1081.         SoundObjects[i].flags = 0;  // Mark as dead, so some other sound can use this sound
  1082.     }
  1083.     digi_sounds_initialized = 1;
  1084.     for (i=0; i<ahidigi_max_channels; i++) ChannelMap[i]=0;
  1085.     #ifdef DEBUG_SOUND
  1086.     hp("Sounds initialized");
  1087.     #endif
  1088. }
  1089.  
  1090. void digi_start_sound_object(int i)
  1091. {
  1092.     ahidigi_param param;
  1093.     if (!Digi_initialized) return;
  1094.  
  1095.  
  1096.     // Sound is not playing, so we must start it again
  1097.     SoundObjects[i].signature=next_signature++;
  1098.                             
  1099.     param.Volume    =   (Fixed)(SoundObjects[i].volume*digi_volume/65535);
  1100.     param.Size      =   GameSounds[SoundObjects[i].soundnum].length;
  1101.     param.Data      =   GameSounds[SoundObjects[i].soundnum].data;
  1102.     param.Pan       =   SoundObjects[i].pan;
  1103.  
  1104.     if (SoundObjects[i].flags & SOF_PLAY_FOREVER )  {
  1105.         param.nLoop = -1;
  1106.     } else param.nLoop = 0;
  1107.  
  1108.     SoundObjects[i].channel = digi_start_sound( ¶m, SoundObjects[i].soundnum );
  1109.  
  1110.     SoundObjects[i].flags |= SOF_PLAYING;
  1111.  
  1112.     ChannelMap[SoundObjects[i].channel] = 1;
  1113.  
  1114. }
  1115.  
  1116. int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix  max_distance )
  1117. {
  1118.     int i,volume,pan;
  1119.     object * objp;
  1120.     int soundnum;
  1121. #ifdef DEBUG_SOUND
  1122. //    HUD_init_message("to_obj(snum=%d,obj=%d,fevr=%d,maxvol=%d,maxdist=%d)",
  1123. //        org_soundnum, objnum, forever, max_volume, max_distance);
  1124. //    printf("to_obj(org_snum=%d,objnum=%d,forever=%d,max_volume=%d,max_distance=%d)\n",
  1125. //        org_soundnum, objnum, forever, max_volume, max_distance);
  1126. #endif
  1127.  
  1128.     soundnum = digi_xlat_sound(org_soundnum);
  1129.  
  1130.     if ( max_volume < 0 ) return -1;
  1131. //  if ( max_volume > F1_0 ) max_volume = F1_0;
  1132.  
  1133.     if (!Digi_initialized) return -1;
  1134.     if (soundnum < 0 ) return -1;
  1135.     if (GameSounds[soundnum].data==NULL) {
  1136.         Int3();
  1137.         return -1;
  1138.     }
  1139.     if ((objnum<0)||(objnum>Highest_object_index))
  1140.         return -1;
  1141.  
  1142.     if ( !forever ) {
  1143.         // Hack to keep sounds from building up...
  1144.         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
  1145.         digi_play_sample_3d( org_soundnum, pan, volume, 0 );
  1146.         return -1;
  1147.     }
  1148.  
  1149.     for (i=0; i<MAX_SOUND_OBJECTS; i++ )
  1150.         if (SoundObjects[i].flags==0)
  1151.             break;
  1152.     
  1153.     if (i==MAX_SOUND_OBJECTS) {
  1154.         mprintf((1, "Too many sound objects!\n" ));
  1155.         return -1;
  1156.     }
  1157.  
  1158.     SoundObjects[i].signature=next_signature++;
  1159.     #ifdef DEBUG_SOUND
  1160.     hp("SOF_PLAYING reset on %d");
  1161.     #endif
  1162.     SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
  1163.     if ( forever )
  1164.         SoundObjects[i].flags |= SOF_PLAY_FOREVER;
  1165.     SoundObjects[i]._objnum = objnum;
  1166.     SoundObjects[i]._objsignature = Objects[objnum].signature;
  1167.     SoundObjects[i].max_volume = max_volume;
  1168.     SoundObjects[i].max_distance = max_distance;
  1169.     SoundObjects[i].volume = 0;
  1170.     SoundObjects[i].pan = 0;
  1171.     SoundObjects[i].soundnum = soundnum;
  1172.  
  1173.     objp = &Objects[SoundObjects[i]._objnum];
  1174.     digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
  1175.                        &objp->pos, objp->segnum, SoundObjects[i].max_volume,
  1176.                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
  1177.  
  1178.     digi_start_sound_object(i);
  1179.  
  1180.     return SoundObjects[i].signature;
  1181. }
  1182.  
  1183. int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
  1184. {                                                                                                   // 10 segs away
  1185.     return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0  );
  1186. }
  1187.  
  1188. int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
  1189. {
  1190.     int i, volume, pan;
  1191.     int soundnum;
  1192. #ifdef DEBUG_SOUND
  1193. //    HUD_init_message("pos(org_sn=%d,seg=%d,maxvol=%d,max_dist=%d)",
  1194. //        org_soundnum, segnum, max_volume, max_distance);
  1195. //    printf("pos(org_sn=%d,seg=%d,maxvol=%d,max_dist=%d)\n",
  1196. //        org_soundnum, segnum, max_volume, max_distance);
  1197. #endif
  1198.  
  1199.     soundnum = digi_xlat_sound(org_soundnum);
  1200.  
  1201.     if ( max_volume < 0 ) return -1;
  1202. //  if ( max_volume > F1_0 ) max_volume = F1_0;
  1203.  
  1204.     if (!Digi_initialized) return -1;
  1205.     if (soundnum < 0 ) return -1;
  1206.     if (GameSounds[soundnum].data==NULL) {
  1207.         Int3();
  1208.         return -1;
  1209.     }
  1210.  
  1211.     if ((segnum<0)||(segnum>Highest_segment_index))
  1212.         return -1;
  1213.  
  1214.     if ( !forever ) {
  1215.         // Hack to keep sounds from building up...
  1216.         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
  1217.         digi_play_sample_3d( org_soundnum, pan, volume, 0 );
  1218.         return -1;
  1219.     }
  1220.  
  1221.     for (i=0; i<MAX_SOUND_OBJECTS; i++ )
  1222.         if (SoundObjects[i].flags==0)
  1223.             break;
  1224.     
  1225.     if (i==MAX_SOUND_OBJECTS) {
  1226.         mprintf((1, "Too many sound objects!\n" ));
  1227.         return -1;
  1228.     }
  1229.  
  1230.  
  1231.     SoundObjects[i].signature=next_signature++;
  1232.     SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
  1233.     #ifdef DEBUG_SOUND
  1234.     hp("SOF_PLAYING reset on %d");
  1235.     #endif
  1236.     if ( forever )
  1237.         SoundObjects[i].flags |= SOF_PLAY_FOREVER;
  1238.     SoundObjects[i]._segnum = segnum;
  1239.     SoundObjects[i]._sidenum = sidenum;
  1240.     SoundObjects[i]._position = *pos;
  1241.     SoundObjects[i].soundnum = soundnum;
  1242.     SoundObjects[i].max_volume = max_volume;
  1243.     SoundObjects[i].max_distance = max_distance;
  1244.     SoundObjects[i].volume = 0;
  1245.     SoundObjects[i].pan = 0;
  1246.     digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
  1247.                        &SoundObjects[i]._position, SoundObjects[i]._segnum, SoundObjects[i].max_volume,
  1248.                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
  1249.     
  1250.     digi_start_sound_object(i);
  1251.  
  1252.     return SoundObjects[i].signature;
  1253. }
  1254.  
  1255. int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
  1256. {
  1257.     return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
  1258. }
  1259.  
  1260.  
  1261. void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
  1262. {
  1263.     int i,killed;
  1264.  
  1265.     soundnum = digi_xlat_sound(soundnum);
  1266.  
  1267.     if (!Digi_initialized) return;
  1268.  
  1269.     killed = 0;
  1270.  
  1271.     for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
  1272.         if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) )  {
  1273.             if ((SoundObjects[i]._segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i]._sidenum==sidenum) ) {
  1274.                 if ( SoundObjects[i].flags & SOF_PLAYING )  {
  1275.                 #ifdef SOUND_DEBUG
  1276.                     printf("Trying to kill sample\n");
  1277.                 #endif
  1278.                     //sosDIGIStopSample( hSOSDigiDriver, SoundObjects[i].handle );
  1279.                 }
  1280.                 #ifdef DEBUG_SOUND
  1281.                 hp("SOF_PLAYING reset on %d");
  1282.                 #endif
  1283.                 SoundObjects[i].flags = 0;  // Mark as dead, so some other sound can use this sound
  1284.                 ChannelMap[SoundObjects[i].channel] = 0;
  1285.                 killed++;
  1286.             }
  1287.         }
  1288.     }
  1289.     // If this assert happens, it means that there were 2 sounds
  1290.     // that got deleted. Weird, get John.
  1291.     if ( killed > 1 )   {
  1292.         mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
  1293.     }
  1294. }
  1295.  
  1296. void digi_kill_sound_linked_to_object( int objnum )
  1297. {
  1298.     int i,killed;
  1299. #ifdef DEBUG_SOUND
  1300.     HUD_init_message("Killing sound linked to object %d\n", objnum);
  1301. #endif
  1302.  
  1303.     if (!Digi_initialized) return;
  1304.  
  1305.     killed = 0;
  1306.  
  1307.     for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
  1308.         if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
  1309.             if (SoundObjects[i]._objnum == objnum)   {
  1310.                 if ( SoundObjects[i].flags & SOF_PLAYING )  {
  1311.                 #ifdef SOUND_DEBUG
  1312.                     printf("Trying to kill sample\n");
  1313.                 #endif
  1314.                     //sosDIGIStopSample( hSOSDigiDriver, SoundObjects[i].handle );
  1315.                 }
  1316.                 #ifdef DEBUG_SOUND
  1317.                 hp("SOF_PLAYING reset on %d");
  1318.                 #endif
  1319.                 SoundObjects[i].flags = 0;  // Mark as dead, so some other sound can use this sound
  1320.                 ChannelMap[SoundObjects[i].channel] = 0;
  1321.                 killed++;
  1322.             }
  1323.         }
  1324.     }
  1325.     // If this assert happens, it means that there were 2 sounds
  1326.     // that got deleted. Weird, get John.
  1327.     if ( killed > 1 )   {
  1328.         mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
  1329.     }
  1330. }
  1331.  
  1332.  
  1333. void digi_sync_sounds()
  1334. {
  1335.     int i;
  1336.     int oldvolume, oldpan;
  1337.  
  1338.     if (!Digi_initialized) return;
  1339.  
  1340.     for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
  1341.         if ( SoundObjects[i].flags & SOF_USED ) {
  1342.             oldvolume = SoundObjects[i].volume;
  1343.             oldpan = SoundObjects[i].pan;
  1344.  
  1345.             if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) )  {
  1346.                 // Check if its done.
  1347.                 if (SoundObjects[i].flags & SOF_PLAYING) {
  1348.                     if (0 == ChannelMap[SoundObjects[i].channel]) {
  1349.                         SoundObjects[i].flags = 0;  // Mark as dead, so some other sound can use this sound
  1350.                         ChannelMap[SoundObjects[i].channel] = 0;
  1351.                         continue;       // Go on to next sound...
  1352.                     }
  1353.                 }
  1354.             }           
  1355.         
  1356.             if ( SoundObjects[i].flags & SOF_LINK_TO_POS )  {
  1357.                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
  1358.                                 &SoundObjects[i]._position, SoundObjects[i]._segnum, SoundObjects[i].max_volume,
  1359.                                 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
  1360.  
  1361.             } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ )   {
  1362.                 object * objp;
  1363.     
  1364.                 objp = &Objects[SoundObjects[i]._objnum];
  1365.         
  1366.                 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i]._objsignature))  {
  1367.                     // The object that this is linked to is dead, so just end this sound if it is looping.
  1368.                     if ( (SoundObjects[i].flags & SOF_PLAYING)  && (SoundObjects[i].flags & SOF_PLAY_FOREVER))  {
  1369.                         AHI_SetSound((UWORD)SoundObjects[i].channel,
  1370.                             AHI_NOSOUND, 0,0, AudioCtrl, AHISF_IMM);
  1371.                     }
  1372.                     SoundObjects[i].flags = 0;  // Mark as dead, so some other sound can use this sound
  1373.                     ChannelMap[SoundObjects[i].channel] = 0;
  1374.                     continue;       // Go on to next sound...
  1375.                 } else {
  1376.                     digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
  1377.                                     &objp->pos, objp->segnum, SoundObjects[i].max_volume,
  1378.                                    &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
  1379.                 }
  1380.             }
  1381.              
  1382.             if (oldvolume != SoundObjects[i].volume)    {
  1383.                 if ( SoundObjects[i].volume < 1 )   {
  1384.                     // Sound is too far away, so stop it from playing.
  1385.                     if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER))  {
  1386.                         AHI_SetSound((UWORD)SoundObjects[i].channel,
  1387.                             AHI_NOSOUND, 0,0, AudioCtrl, AHISF_IMM);
  1388.                         SoundObjects[i].flags &= ~SOF_PLAYING;      // Mark sound as not playing
  1389.                         ChannelMap[SoundObjects[i].channel] = 0;
  1390.                     }
  1391.                 } else {
  1392.                     if (!(SoundObjects[i].flags & SOF_PLAYING)) {
  1393.                         digi_start_sound_object(i);
  1394.                     } else {
  1395.                         //sosDIGISetSampleVolume( hSOSDigiDriver,
  1396.                         //    SoundObjects[i].handle,
  1397.                         //    fixmuldiv(SoundObjects[i].volume,
  1398.                         //        digi_volume,F1_0) );
  1399.                         AHI_SetVol((UWORD)SoundObjects[i].channel,
  1400.                             (Fixed)(SoundObjects[i].volume*digi_volume/65535),
  1401.                             (sposition)SoundObjects[i].pan,
  1402.                             AudioCtrl, AHISF_IMM);
  1403.                     }
  1404.                 }
  1405.             }
  1406.         }
  1407.     }
  1408. }
  1409.  
  1410.  
  1411. int sound_paused = 0;
  1412.  
  1413. void digi_pause_all()
  1414. {
  1415.     if (!Digi_initialized) return;
  1416.     sound_paused++;
  1417.  
  1418.     if (sound_paused > 1) return;
  1419.     AHI_ControlAudio(AudioCtrl,
  1420.         AHIC_Play,  FALSE,
  1421.     TAG_DONE);
  1422. }
  1423.  
  1424. void digi_resume_all()
  1425. {
  1426.     if (!Digi_initialized) return;
  1427.     if (sound_paused > 0) sound_paused--;
  1428.     if (sound_paused > 0) return;
  1429.     AHI_ControlAudio(AudioCtrl,
  1430.         AHIC_Play, TRUE,
  1431.     TAG_DONE);
  1432. }
  1433.  
  1434.  
  1435. void digi_stop_all()
  1436. {
  1437.     int i;
  1438.  
  1439.     if (!Digi_initialized) return;
  1440.  
  1441.     for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
  1442.         if ( SoundObjects[i].flags & SOF_USED ) {
  1443.             #ifdef DEBUG_SOUND
  1444.             hp("SOF_PLAYING reset on %d");
  1445.             #endif
  1446.             SoundObjects[i].flags = 0;  // Mark as dead, so some other sound can use this sound
  1447.         }
  1448.     }
  1449.  
  1450.     for (i=0; i<ahidigi_max_channels; i++) {
  1451.         AHI_SetSound(i, AHI_NOSOUND, 0, 0, AudioCtrl, AHISF_IMM);
  1452.         ChannelMap[i] = 0;
  1453.     }
  1454.  
  1455. }
  1456.  
  1457. #ifndef NDEBUG
  1458. int verify_sound_channel_free( int channel )
  1459. {
  1460.     return 0;
  1461. }
  1462. #endif
  1463.